import React, { useContext, useMemo } from "react";
import classnames from "classnames";
import { isUndefined } from "@ct0/functions";

import type { FormViewProps, FieldBaseType, FieldType } from "./type";
import { ThemeContext } from "../theme";
import FormItem from "./FormItem";
import validator from "./validator";

export default FormView;

function FormView<FIELD extends FieldBaseType = FieldType>({
  title,
  form,
  fields: propsFields = [],
  showError = false,
  justify,
  labelWidth,
  onChange: propsOnChange,
  column = 1,
}: FormViewProps<FIELD>) {
  const fields = form?.fields || propsFields;

  const values = fields.map((i) =>
    isUndefined(i.value) ? i.defaultValue : i.value
  );

  const { fontSize } = useContext(ThemeContext);

  const validation = useMemo(() => {
    const result: Array<{
      isValid: boolean;
      errmsg: string;
    }> = [];

    for (let i = 0; i < fields.length; i++) {
      const [isValid, errmsg] = validator(fields[i], values?.[i]);
      result.push({ isValid, errmsg });
    }
    return result;
  }, [values, fields]);

  const handler = (index: number, v: any) => {
    const [isValid] = validator(fields[index], v);
    const isAllValid = validation.reduce(
      (r, i, idx) => r && (index == idx ? isValid : i.isValid),
      true
    );
    const newValues = [...values];
    newValues[index] = v;
    form?.onChange?.(newValues, isAllValid);

    const kvData: Record<string, any> = {};
    for (let i = 0; i < fields.length; i++) {
      kvData[fields[i].key] = newValues[i];
    }

    const arrData = newValues.map((i, index) => ({
      key: fields[index].key,
      value: i,
    }));

    propsOnChange?.(kvData, isAllValid, arrData);
  };

  return (
    <>
      <div className="ct0-formview">
        {title && (
          <div className="ct0-formview-title" style={{ fontSize }}>
            {title}
          </div>
        )}
        <div className="ct0-formview-content">
          {fields.map((i, index) => {
            return (
              <div
                key={index}
                className={classnames([
                  column == 1 && "ct0-formview-column1",
                  column == 2 && "ct0-formview-column2",
                  column == 3 && "ct0-formview-column3",
                ])}
              >
                <FormItem
                  isLast={index == fields.length - 1}
                  field={i}
                  justify={justify}
                  isValid={validation[index].isValid}
                  errmsg={validation[index].errmsg}
                  showError={showError}
                  labelWidth={labelWidth}
                  index={index}
                  onChange={handler}
                />
              </div>
            );
          })}
        </div>
      </div>
    </>
  );
}
